package com.seecen.webproject.dao;

import com.seecen.webproject.utils.MyUtils;

import java.io.InputStream;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.*;

public class BaseDao {
    private static final String URL;
    private static final String USERNAME;
    private static final String PASSWORD;

    static {
        InputStream is = BaseDao.class.getClassLoader().getResourceAsStream("jdbc.properties");
        Properties properties = MyUtils.getProperties(is);
        String driver = properties.get("JDBC.DRIVER").toString();
        URL = properties.get("JDBC.URL").toString();
        USERNAME = properties.get("JDBC.USERNAME").toString();
        PASSWORD = properties.get("JDBC.PASSWORD").toString();
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public int queryCount(String sql, Object... param) {
        try (
                Connection con = getConnection();
                PreparedStatement pstm = con.prepareStatement(sql);
        ) {
            for (int i = 0; i < param.length; i++) {
                pstm.setObject(i + 1, param[i]);
            }
            try (ResultSet rs = pstm.executeQuery()) {
               if(rs.next()) {
                   return rs.getInt(1);
               }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    public <T> List<T> query(Class<T> clazz, String sql, Object... param) {
        // 获取到要查询的对象的所有属性
        Map<String, Class> map = getJavaBeanProperties(clazz);

        List<T> list = new ArrayList<>();

        try (
                Connection con = getConnection();
                PreparedStatement pstm = con.prepareStatement(sql);
        ) {
            for (int i = 0; i < param.length; i++) {
                pstm.setObject(i + 1, param[i]);
            }
            try (ResultSet rs = pstm.executeQuery()) {
                while (rs.next()) {
                    // 反射创建一个对象
                    T entity = clazz.newInstance();
                    for (Map.Entry<String, Class> entry : map.entrySet()) {
                        String columnName = entry.getKey();
                        // 获取entity对应的set方法
                        Method method = clazz.getMethod("set" + columnName, entry.getValue());
                        // 将驼峰命名转换为匈牙利
                        String dbColumnName = MyUtils.humpConvertHungary(columnName);
                        if (entry.getValue() == Integer.class) method.invoke(entity, rs.getInt(dbColumnName));
                        if (entry.getValue() == String.class) method.invoke(entity, rs.getString(dbColumnName));
                        if (entry.getValue() == Double.class) method.invoke(entity, rs.getDouble(dbColumnName));
                    }
                    list.add(entity);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return list;
    }

    private <T> Map<String, Class> getJavaBeanProperties(Class<T> clazz) {
        Method[] methods = clazz.getMethods();
        Map<String, Class> map = new HashMap<>();
        for (Method method : methods) {
            if(method.getName().startsWith("set")) {
                map.put(method.getName().substring(3), method.getParameterTypes()[0]);
            }
        }
        return map;
    }

    // update table set a=?,b=? where ..
    // deete..
    public int doUpdate(String sql, Object... param) {
        int res = 0;
        try (
                Connection con = getConnection();
                PreparedStatement ps = con.prepareStatement(sql);
        ) {
            // sql = update table set a=?,b=? where c= ?
            // doUpdate(sql, 10, 20, 9527);
            for (int i = 0; i < param.length; i++) {
                ps.setObject(i + 1, param[i]);
            }
            res = ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return res;
    }


    private Connection getConnection() {
        try {
            return DriverManager.getConnection(URL, USERNAME, PASSWORD);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

}
